﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Finance.Data.Entities
{
	public class DocumentSubTypes
	{
		private readonly FinanceDataBase _dataBase;
		private const string RetrieveDocumentSubTypesQuery =
			"select * from documentsubtype where typecode = @p0 order by name";
		
		private const string CreateDocumentSubTypeQuery =
			"insert into documentsubtype (documentsubtypeid, name, typecode) values (@p0, @p1, @p2)";

		internal DocumentSubTypes(FinanceDataBase dataBase)
		{
			_dataBase = dataBase;
		}

		public Dictionary<DocumentType, Dictionary<string, Guid>> SubTypes;

		public void Update()
		{
			SubTypes = new Dictionary<DocumentType, Dictionary<string, Guid>>();

			foreach (var documentType in _dataBase.DocumentTypes)
			{
				Dictionary<string, Guid> subTypes = RetrieveDocumentSubTypes(documentType);

				SubTypes.Add(documentType, subTypes);
			}
		}

		public Guid CheckSubType(DocumentType documentType, string documentSubTypeName)
		{
			Guid documentSubTypeId;

			if (!SubTypes[documentType].ContainsKey(documentSubTypeName))
			{
				try
				{
					documentSubTypeId = CreateDocumentSubType(documentType, documentSubTypeName);
				}
				catch (Exception exception)
				{
					throw new Exception("Ошибка при заведении нового типа доходов в базе данных.", exception);
				}
				Update();
			}
			else
			{
				documentSubTypeId = SubTypes[documentType][documentSubTypeName];
			}
			return documentSubTypeId;
		}

		internal string[] GetAllowedSubTypes(Document document)
		{
			return SubTypes[document.DocumentType].Keys.ToArray();
		}

		public Dictionary<string, Guid> RetrieveDocumentSubTypes(DocumentType documentType)
		{
			var result = new Dictionary<string, Guid>();

			using (var dataReader = _dataBase.Sql.ExecuteReader(
				RetrieveDocumentSubTypesQuery,
				(int)documentType))
			{
				while (dataReader.Read())
				{
					if (dataReader["name"] != DBNull.Value)
					{
						var documentName = (string)dataReader["name"];
						if (!result.ContainsKey(documentName))
						{
							var documentTypeId = (Guid)dataReader["documentsubtypeid"];
							result.Add(documentName, documentTypeId);
						}
					}
				}
			}
			return result;
		}

		internal Guid CreateDocumentSubType(DocumentType documentType, string subTypeName)
		{
			var newDocumentSubTypeId = Guid.NewGuid();

			_dataBase.Sql.ExecuteNonQuery( 
				CreateDocumentSubTypeQuery, 
				newDocumentSubTypeId,
				subTypeName,
				(int)documentType);

			return newDocumentSubTypeId;
		}

		public IEnumerable<string> RetrieveNames(DocumentType documentType)
		{
			using (var dataReader = _dataBase.Sql.ExecuteReader( RetrieveDocumentSubTypesQuery, (int)documentType))
			{
				while (dataReader.Read())
				{
					if (dataReader["name"] != DBNull.Value)
					{
						yield return (string) dataReader["name"];
					}
				}
			}
		}
	}
}
